MediaDock:服务端项目介绍与 Flutter 开发说明
1. 项目定位
MediaDock 是面向个人 NAS 的本地媒体管理与播放服务。NAS 只运行服务端,Flutter 负责所有客户端功能。
本项目不依赖 Jellyfin、Komga、下载器或外部资源搜索服务。媒体内容全部来自 NAS 上用户自行配置并有权访问的本地目录。
2. 总体架构
Flutter 客户端
│ HTTP / HTTPS
▼
MediaDock 服务端
├── FastAPI API
├── PostgreSQL 元数据数据库
├── 本地媒体扫描器
├── 视频/音频流转发
├── 小说章节读取
├── 漫画图片读取
└── 播放与阅读进度
│
▼
NAS 本地媒体目录Web 管理后台不再作为产品客户端;后续所有播放、阅读和管理页面统一使用 Flutter 实现。
3. 支持的媒体类型
视频
第一版支持:mp4、mkv、avi、mov、webm、m4v、ts。
服务端保存文件信息、时长、分辨率、编码、封面和播放进度。播放采用原文件转发,接口必须支持 HTTP Range,以便断点播放和拖动进度。第一版暂不做 FFmpeg 转码。
音频
第一版支持:mp3、flac、m4a、aac、ogg、wav。
优先读取 ID3、FLAC 或 MP4 标签;缺少标签时从文件名和目录名推断歌曲、专辑和歌手信息。
小说
第一版支持:txt、md、epub。
TXT/Markdown 按章节解析,EPUB 解析书名、作者、封面、目录和正文。正文按章节接口读取,不一次性返回整本书。
漫画
第一版支持图片目录和 cbz,图片格式包括 jpg、jpeg、png、webp。
CBZ 按 ZIP 图片包处理,按页提供图片接口。暂不支持 CBR。
4. 本地目录规划
建议统一挂载:
volumes:
- ./data/media:/data/media:ro容器内目录示例:
/data/media/
├── movies/
├── tv/
├── music/
├── novels/
├── manga/
└── .metadata/
├── posters/
├── backdrops/
└── covers/服务端只允许读取 /data/media 及其子目录,防止路径越界。
目录配置支持多个媒体库,每个目录包含名称、相对路径、媒体类型、启用状态、扫描状态、文件数量和最后扫描时间。
5. 扫描机制
扫描器负责发现新文件、更新已变化文件,并将不存在的文件标记为不可用,不直接删除用户数据。
建议先支持手动扫描全部目录或单个目录,之后增加定时扫描和增量扫描。
扫描结果至少包含:文件名、相对路径、文件大小、MIME 类型、修改时间、媒体类型、封面路径、解析出的标题、季集数和元数据状态。
6. 服务端接口概览
认证
POST /api/auth/login
GET /api/auth/getUserInfo
POST /api/auth/refreshToken目录与扫描
GET /api/directories
POST /api/directories
PATCH /api/directories/{id}
DELETE /api/directories/{id}
POST /api/directories/{id}/scan
POST /api/directories/scan
GET /api/scans/{id}媒体
GET /api/media
GET /api/media/{id}
GET /api/media/{id}/cover
GET /api/media/{id}/stream媒体列表支持类型、目录、关键词和分页筛选。视频与音频统一使用 stream 接口,根据媒体类型返回正确的 MIME 类型,并支持 Range 请求。
小说阅读
GET /api/books/{id}
GET /api/books/{id}/chapters
GET /api/books/{id}/chapters/{chapter_id}漫画阅读
GET /api/manga/{id}
GET /api/manga/{id}/chapters
GET /api/manga/{id}/chapters/{chapter_id}/pages
GET /api/manga/{id}/chapters/{chapter_id}/pages/{page}进度与收藏
GET /api/progress
PUT /api/media/{id}/progress
PUT /api/books/{id}/progress
PUT /api/manga/{id}/progress
GET /api/favorites
POST /api/favorites/{media_id}
DELETE /api/favorites/{media_id}7. 视频刮削与 TMDB
视频刮削是可选功能,不影响本地扫描和播放。
TMDB 用于获取:
- 中文及原标题
- 简介
- 年份
- 类型
- 演员和导演
- 评分
- 海报
- 背景图
- 电视剧季集信息
推荐流程:
扫描本地文件
→ 解析文件名和年份
→ TMDB 搜索候选
→ 用户在 Flutter 中确认
→ 保存 TMDB ID 和元数据
→ 下载并缓存海报、背景图建议服务端配置:
TMDB_API_KEY=
TMDB_API_READ_TOKEN=
TMDB_LANGUAGE=zh-CN没有 TMDB Key 时,仍然可以使用本地文件扫描、播放、搜索和进度功能;只是不能自动获取在线影视信息。海报优先使用本地伴随图片,其次才使用 TMDB 缓存图片。
使用 TMDB 数据和图片时,应遵守 TMDB 当前 API 使用条款并保留必要署名。TMDB 只提供元数据,不提供影视文件。
8. Flutter 客户端规划
Flutter 是唯一客户端,使用统一 API 完成:
- 登录与令牌管理
- 首页和媒体库
- 视频播放
- 音乐播放、队列和后台播放
- 小说目录与章节阅读
- 漫画图片阅读
- 播放和阅读进度同步
- 收藏与历史
- 管理员目录配置和扫描
- TMDB 候选匹配与刮削管理
建议技术选型:
| 库 | 用途 |
|---|---|
| Dio | HTTP 请求 |
| GetX | 状态管理和路由 |
| just_audio | 音乐播放 |
| media_kit | 视频播放,待最终验证 |
| get_storage | 本地令牌和客户端偏好 |
Flutter 不直接访问 NAS 文件系统,只通过服务端 API 访问媒体;播放地址携带认证信息或使用短期播放令牌。
9. 安全要求
- 所有业务接口保留登录鉴权。
- 文件路径必须限制在
/data/media内。 - 禁止通过参数读取任意宿主机文件。
- 视频、音频、图片接口检查文件存在性和媒体归属。
- 生产环境不展示数据库错误堆栈。
- TMDB 凭据只保存在服务端,不放入 Flutter 客户端。
- 媒体目录使用只读挂载,避免服务端误修改原始文件。
- 播放和阅读进度写入 PostgreSQL,客户端只缓存临时状态。
10. 明确移除的功能
本版本不包含:
- Web 前端和浏览器后台
- Jellyfin
- Komga
- 下载中心
- 磁力链接和 BT 下载
- qBittorrent、Transmission、aria2
- 外部资源搜索
- 在线字幕下载
- 视频转码
- CBR、PDF、DOCX 阅读
11. 开发顺序
服务端阶段
- 纯 API Docker 部署收口。
- 新增多媒体目录和扫描任务模型。
- 实现视频、音频、小说、漫画扫描。
- 实现媒体列表、详情、封面和本地搜索。
- 实现 Range 流转发。
- 实现小说章节和漫画页面接口。
- 实现播放/阅读进度与收藏。
- 实现可选 TMDB 刮削。
- 固化 Flutter API 契约。
Flutter 阶段
- 登录。
- 首页和媒体库。
- 视频播放。
- 音乐播放。
- 小说阅读。
- 漫画阅读。
- 进度、收藏和历史。
- 目录管理、扫描管理和 TMDB 刮削管理。
12. 版本目标
建议服务端版本:MediaDock v1.1.0。
目标是建立一个稳定的 NAS 本地媒体 API,让 Flutter 成为统一客户端。第一版优先保证本地媒体读取、播放、阅读和进度同步,复杂的转码、联网刮削扩展和多用户能力放到后续版本。